package p.ithorns.sample.refresh;

import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.*;
import org.springframework.boot.context.properties.bind.handler.IgnoreErrorsBindHandler;
import org.springframework.boot.context.properties.bind.handler.IgnoreTopLevelConverterNotFoundBindHandler;
import org.springframework.boot.context.properties.bind.handler.NoUnboundElementsBindHandler;
import org.springframework.boot.context.properties.source.ConfigurationPropertySources;
import org.springframework.boot.context.properties.source.UnboundElementsSourceFilter;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.event.EventListener;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.convert.support.DefaultConversionService;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertySourcesPropertyResolver;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.stereotype.Service;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.ClassUtils;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * ConfigRefreshService
 *
 * @author HtL
 * @date 2024/12/10 14:14
 * @since 1.0.0
 */
@Slf4j
@Service
public class ConfigRefreshService {
    /**
     * 路径匹配器
     */
    private final AntPathMatcher pathMatcher = new AntPathMatcher(".");

    private final ApplicationContext appCtx;

    private final ConfigurableEnvironment env;

    private final Binder binder;

    private ConfigChangeListener listener;

    // private final ApplicationEventPublisher eventPublisher;

    public ConfigRefreshService(ApplicationContext appCtx,
                                ConfigurableEnvironment env,
                                ConfigChangeListener listener) {
        this.appCtx = appCtx;
        this.env = env;
        this.listener = listener;

        this.binder = new Binder(ConfigurationPropertySources.from(env.getPropertySources()),
                new PropertySourcesPlaceholdersResolver(env),
                new DefaultConversionService(),
                ((ConfigurableApplicationContext) appCtx).getBeanFactory()::copyRegisteredEditorsTo);
    }

    @EventListener
    public void refreshConfig(ConfigChangeListener.RefreshEvent event) {
        System.out.println("=============> 刷新Config ");
        // 刷新类注解
        Map<String, Object> beansWithAnnotation = appCtx.getBeansWithAnnotation(ConfigurationProperties.class);
        for (Map.Entry<String, Object> entry : beansWithAnnotation.entrySet()) {
            Object bean = entry.getValue();
            Class<?> aClass = bean.getClass();
            ConfigurationProperties cp = AnnotationUtils.findAnnotation(aClass, ConfigurationProperties.class);
            Bindable<?> target = Bindable.ofInstance(bean).withAnnotations(cp);
            bind(target);
        }
    }

    /**
     * 重新绑定bean对象对应的配置值
     */
    public <T> void bind(Bindable<T> bindable) {
        ConfigurationProperties propertiesAno = bindable.getAnnotation(ConfigurationProperties.class);
        if (propertiesAno != null) {
            BindHandler bindHandler = getBindHandler(propertiesAno);
            String key = propertiesAno.prefix();
            this.binder.bind(key, bindable, bindHandler);
        }
    }

    private BindHandler getBindHandler(ConfigurationProperties annotation) {
        BindHandler handler = new IgnoreTopLevelConverterNotFoundBindHandler();
        if (annotation.ignoreInvalidFields()) {
            handler = new IgnoreErrorsBindHandler(handler);
        }
        if (!annotation.ignoreUnknownFields()) {
            UnboundElementsSourceFilter filter = new UnboundElementsSourceFilter();
            handler = new NoUnboundElementsBindHandler(handler, filter);
        }
        return handler;
    }


    public static void main(String[] args) {
        String p = "app.user.**";
        AntPathMatcher matcher = new AntPathMatcher(".");
        boolean match = matcher.match(p, "app.user.debug.enabled");
        System.out.println(match);
    }


    static class RefreshEvent extends ApplicationEvent {
        public RefreshEvent(Object source) {
            super(source);
        }

        public RefreshEvent(Object source, Object origin) {
            super(source);
        }

        public RefreshEvent(Object source, Object origin, String message) {
            super(source);
            // 可以添加更多逻辑，如日志记录等
        }
    }

}